package dryven.model.binding.proxy;

import java.lang.reflect.Method;
import dryven.model.binding.fieldset.BoundField;

public class BindingProxy implements CallInterceptor {
	
	private static CallInterceptorStubClassLoader _classLoader;
	private Method _calledMethod;
	private Object[] _calledParams;
	
	static {
		_classLoader = new CallInterceptorStubClassLoader(BindingProxy.class.getClassLoader());
	}
	
	public BindingProxy() {
		
	}
	
	public <T> Binding<T> newBinding(T val) {
		return new Binding<T>(this,val);
	}
	
	public BoundField newField(Object o) {
		return new BoundField(newBinding(o));
	}
	
	@SuppressWarnings("unchecked")
	public <T> T byClass(Class<T> clazz) {
		reset();
		return (T)createProxyObject(clazz);
	}
	
	@SuppressWarnings("unchecked")
	public <T> T byObject(T o) {
		reset();
		return (T)createProxyObject(o.getClass());
	}
	
	public Method getCalledMethod() {
		if(_calledMethod==null) {
			throw new RuntimeException("You forgot to call the getter on the proxy object, or you called a generic method which is not supported yet");
		}
		Method m = _calledMethod;
		_calledMethod = null;
		return m;
	}
	
	protected Object createProxyObject(Class<?> type) {
		try {
			Class<?> currentProxyClass = _classLoader.loadClass(_classLoader.getProxyClassName(type));

			return currentProxyClass.getConstructor(new Class[]{CallInterceptor.class}).newInstance(new Object[]{this});
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	protected void reset() {
		_calledMethod = null;
	}
	
	public void methodCalled(Method m, Object[] params) {
		_calledMethod = m;
		_calledParams = params;
	}
	
	public Object[] getCalledParams() {
		return _calledParams;
	}
}
